<template>
  <ul
    v-if="!contactSearchingStatus"
    :class="['tui-contact-list', !isPC && 'tui-contact-list-h5']"
  >
    <li
      v-for="(contactListObj, key) in sortContactListMap"
      :key="key"
      class="tui-contact-list-item"
    >
      <header
        class="tui-contact-list-item-header"
        @click="toggleCurrentContactList(key)"
      >
        <div class="tui-contact-list-item-header-left">
          <Icon
            :file="currentContactListKey === key ? downSVG : rightSVG"
            width="16px"
            height="16px"
          />
          <div>{{ TUITranslateService.t(`TUIContact.${contactListObj.title}`) }}</div>
        </div>
        <div class="tui-contact-list-item-header-right">
          <span
            v-if="contactListObj.unreadCount"
            class="tui-contact-list-item-header-right-unread"
          >
            {{ contactListObj.unreadCount }}
          </span>
        </div>
      </header>
      <ul :class="['tui-contact-list-item-main', currentContactListKey === key ? '' : 'hidden']">
        <template v-if="key === 'friendList'">
          <div
            v-for="(groupData, groupKey) in contactListObj.list"
            :key="groupKey"
          >
            <div class="tui-contact-list-group-title">
              {{ groupKey }} ({{ groupData.length }})
            </div>
            <li
              v-for="contactListItem in groupData"
              :key="contactListItem.renderKey"
              class="tui-contact-list-item-main-item"
              :class="['selected']"
              @click="selectItem(contactListItem)"
            >
              <ContactListItem
                :key="contactListItem.renderKey"
                :item="deepCopy(contactListItem)"
                :display-online-status="displayOnlineStatus"
              />
            </li>
          </div>
        </template>
        <template v-else>
          <li
            v-for="contactListItem in contactListObj.list"
            :key="contactListItem.renderKey"
            class="tui-contact-list-item-main-item"
            :class="['selected']"
            @click="selectItem(contactListItem)"
          >
            <ContactListItem
              :key="contactListItem.renderKey"
              :item="deepCopy(contactListItem)"
            />
          </li>
        </template>
      </ul>
    </li>
  </ul>
  <ul
    v-else
    class="tui-contact-list"
  >
    <li
      v-for="(item, key) in contactSearchResult"
      :key="key"
      class="tui-contact-list-item"
    >
      <div
        v-if="item.list[0]"
        class="tui-contact-search-list"
      >
        <div class="tui-contact-search-list-title">
          {{ TUITranslateService.t(`TUIContact.${item.label}`) }}
        </div>
        <div
          v-for="(listItem, index) in item.list"
          :key="index"
          class="tui-contact-search-list-item"
          :class="['selected']"
          @click="selectItem(listItem)"
        >
          <ContactListItem
            :item="listItem"
            :display-online-status="false"
          />
        </div>
      </div>
    </li>
    <div
      v-if="isContactSearchNoResult"
      class="tui-contact-search-list-default"
    >
      {{ TUITranslateService.t("TUIContact.无搜索结果") }}
    </div>
  </ul>
</template>
<script setup lang="ts">
import {
  TUITranslateService,
  TUIStore,
  StoreName,
  TUIFriendService,
  TUIUserService,
} from '@tencentcloud/chat-uikit-engine-lite';
import TUICore, { TUIConstants } from '@tencentcloud/tui-core-lite';
import { ref, computed, onMounted, onUnmounted, provide } from '../../../adapter-vue';
import downSVG from '../../../assets/icon/down-icon.svg';
import rightSVG from '../../../assets/icon/right-icon.svg';
import { isPC } from '../../../utils/env';
import Icon from '../../common/Icon.vue';
import { deepCopy } from '../../TUIChat/utils/utils';
import { sortByFirstChar } from '../utils/sortByFirstChar';
import ContactListItem from './contact-list-item/index.vue';
import type {
  IContactList,
  IContactSearchResult,
  IBlackListUserItem,
  IUserStatus,
  IUserStatusMap,
  IContactInfoType,
} from '../../../interface';
import type {
  IGroupModel,
  Friend,
  FriendApplication } from '@tencentcloud/chat-uikit-engine-lite';

const currentContactListKey = ref<keyof IContactList>('');
const currentContactInfo = ref<IContactInfoType>({} as IContactInfoType);
const contactListMap = ref<IContactList>({
  friendApplicationList: {
    key: 'friendApplicationList',
    title: '新的联系人',
    list: [] as FriendApplication[],
    unreadCount: 0,
  },
  blackList: {
    key: 'blackList',
    title: '黑名单',
    list: [] as IBlackListUserItem[],
  },
  groupList: {
    key: 'groupList',
    title: '我的群聊',
    list: [] as IGroupModel[],
  },
  friendList: {
    key: 'friendList',
    title: '我的好友',
    list: [] as Friend[],
  },
});
const sortContactListMap = computed(() => {
  const { groupedList } = sortByFirstChar(
    contactListMap.value?.friendList?.list,
    (friend: Friend) => friend.remark || friend.profile?.nick || friend.userID || '');
  return {
    ...contactListMap.value,
    friendList: {
      ...contactListMap.value?.friendList,
      list: groupedList,
    },
  };
});
const contactSearchingStatus = ref<boolean>(false);
const contactSearchResult = ref<IContactSearchResult>();
const displayOnlineStatus = ref<boolean>(false);
const userOnlineStatusMap = ref<IUserStatusMap>();

const isContactSearchNoResult = computed((): boolean => (
  !contactSearchResult?.value?.user?.list[0]
  && !contactSearchResult?.value?.group?.list[0]
));

onMounted(() => {
  TUIStore.watch(StoreName.APP, {
    enabledCustomerServicePlugin: onCustomerServiceCommercialPluginUpdated,
  });

  TUIStore.watch(StoreName.GRP, {
    groupList: onGroupListUpdated,
  });

  TUIStore.watch(StoreName.USER, {
    userBlacklist: onUserBlacklistUpdated,
    displayOnlineStatus: onDisplayOnlineStatusUpdated,
    userStatusList: onUserStatusListUpdated,
  });

  TUIStore.watch(StoreName.FRIEND, {
    friendList: onFriendListUpdated,
    friendApplicationList: onFriendApplicationListUpdated,
    friendApplicationUnreadCount: onFriendApplicationUnreadCountUpdated,
  });

  TUIStore.watch(StoreName.CUSTOM, {
    currentContactSearchingStatus: onCurrentContactSearchingStatusUpdated,
    currentContactSearchResult: onCurrentContactSearchResultUpdated,
    currentContactListKey: onCurrentContactListKeyUpdated,
    currentContactInfo: onCurrentContactInfoUpdated,
  });
});

onUnmounted(() => {
  TUIStore.unwatch(StoreName.APP, {
    enabledCustomerServicePlugin: onCustomerServiceCommercialPluginUpdated,
  });

  TUIStore.unwatch(StoreName.GRP, {
    groupList: onGroupListUpdated,
  });

  TUIStore.unwatch(StoreName.USER, {
    userBlacklist: onUserBlacklistUpdated,
    displayOnlineStatus: onDisplayOnlineStatusUpdated,
    userStatusList: onUserStatusListUpdated,
  });

  TUIStore.unwatch(StoreName.FRIEND, {
    friendList: onFriendListUpdated,
    friendApplicationList: onFriendApplicationListUpdated,
    friendApplicationUnreadCount: onFriendApplicationUnreadCountUpdated,
  });

  TUIStore.unwatch(StoreName.CUSTOM, {
    currentContactSearchingStatus: onCurrentContactSearchingStatusUpdated,
    currentContactSearchResult: onCurrentContactSearchResultUpdated,
    currentContactListKey: onCurrentContactListKeyUpdated,
    currentContactInfo: onCurrentContactInfoUpdated,
  });
});

function toggleCurrentContactList(key: keyof IContactList) {
  if (currentContactListKey.value === key) {
    currentContactListKey.value = '';
    currentContactInfo.value = {} as IContactInfoType;
    TUIStore.update(StoreName.CUSTOM, 'currentContactListKey', '');
    TUIStore.update(StoreName.CUSTOM, 'currentContactInfo', {} as IContactInfoType);
  } else {
    currentContactListKey.value = key;
    TUIStore.update(StoreName.CUSTOM, 'currentContactListKey', key);
    if (key === 'friendApplicationList') {
      TUIFriendService.setFriendApplicationRead();
    }
  }
}

function selectItem(item: any) {
  currentContactInfo.value = item;
  // For a result in the search list, before viewing the contactInfo details,
  // it is necessary to update the data for the "already in the group list/already in the friend list" situation to obtain more detailed information
  if (contactSearchingStatus.value) {
    let targetListItem;
    if ((currentContactInfo.value as Friend)?.userID) {
      targetListItem = contactListMap.value?.friendList?.list?.find(
        (item: IContactInfoType) => (item as Friend)?.userID === (currentContactInfo.value as Friend)?.userID,
      );
    } else if ((currentContactInfo.value as IGroupModel)?.groupID) {
      targetListItem = contactListMap.value?.groupList?.list?.find(
        (item: IContactInfoType) => (item as IGroupModel)?.groupID === (currentContactInfo.value as IGroupModel)?.groupID,
      );
    }
    if (targetListItem) {
      currentContactInfo.value = targetListItem;
    }
  }
  TUIStore.update(StoreName.CUSTOM, 'currentContactInfo', currentContactInfo.value);
}

function onDisplayOnlineStatusUpdated(status: boolean) {
  displayOnlineStatus.value = status;
}

function onUserStatusListUpdated(list: Map<string, IUserStatus>) {
  if (list?.size > 0) {
    userOnlineStatusMap.value = Object.fromEntries(list?.entries());
  }
}

function onCustomerServiceCommercialPluginUpdated(isEnabled: boolean) {
  if (!isEnabled) {
    return;
  }

  // After the customer purchases the customer service plug-in,
  // the engine updates the enabledCustomerServicePlugin to true through the commercial capability bit.
  const contactListExtensionID = TUIConstants.TUIContact.EXTENSION.CONTACT_LIST.EXT_ID;
  const tuiContactExtensionList = TUICore.getExtensionList(contactListExtensionID);

  const customerData = tuiContactExtensionList.find((extension: any) => {
    const { name, accountList = [] } = extension.data || {};
    return name === 'customer' && accountList.length > 0;
  });

  if (customerData) {
    const { data, text } = customerData;
    const { accountList } = (data || {}) as { accountList: string[] };

    TUIUserService.getUserProfile({ userIDList: accountList })
      .then((res) => {
        if (res.data.length > 0) {
          const customerList = {
            title: text,
            list: res.data.map((item: any, index: number) => ({
              ...item,
              renderKey: generateRenderKey('customerList', item, index),
              infoKeyList: [],
              btnKeyList: ['enterC2CConversation'],
            })),
            key: 'customerList',
          };
          contactListMap.value = { ...contactListMap.value, customerList };
        }
      })
      .catch(() => { });
  }
}

function onGroupListUpdated(groupList: IGroupModel[]) {
  updateContactListMap('groupList', groupList);
}

function onUserBlacklistUpdated(userBlacklist: IBlackListUserItem[]) {
  updateContactListMap('blackList', userBlacklist);
}

function onFriendApplicationUnreadCountUpdated(friendApplicationUnreadCount: number) {
  contactListMap.value.friendApplicationList.unreadCount = friendApplicationUnreadCount;
}

function onFriendListUpdated(friendList: Friend[]) {
  updateContactListMap('friendList', friendList);
}

function onFriendApplicationListUpdated(friendApplicationList: FriendApplication[]) {
  updateContactListMap('friendApplicationList', friendApplicationList);
}

function updateContactListMap(key: keyof IContactList, list: IContactInfoType[]) {
  contactListMap.value[key].list = list;
  contactListMap.value[key].list.map((item: IContactInfoType, index: number) => item.renderKey = generateRenderKey(key, item, index));
  updateCurrentContactInfoFromList(contactListMap.value[key].list, key);
}

function updateCurrentContactInfoFromList(list: IContactInfoType[], type: keyof IContactList) {
  if (
    !(currentContactInfo.value as Friend)?.userID
    && !(currentContactInfo.value as IGroupModel)?.groupID
  ) {
    return;
  }
  if (type === currentContactListKey.value || contactSearchingStatus.value) {
    currentContactInfo.value = list?.find(
      (item: any) =>
        (item?.groupID && item?.groupID === (currentContactInfo.value as IGroupModel)?.groupID) || (item?.userID && item?.userID === (currentContactInfo.value as Friend)?.userID),
    ) || {} as IContactInfoType;
    TUIStore.update(StoreName.CUSTOM, 'currentContactInfo', currentContactInfo.value);
  }
}

function generateRenderKey(contactListMapKey: keyof IContactList, contactInfo: IContactInfoType, index: number) {
  return `${contactListMapKey}-${(contactInfo as Friend).userID || (contactInfo as IGroupModel).groupID || (`index${index}`)}`;
}

function onCurrentContactSearchResultUpdated(searchResult: IContactSearchResult) {
  contactSearchResult.value = searchResult;
}

function onCurrentContactSearchingStatusUpdated(searchingStatus: boolean) {
  contactSearchingStatus.value = searchingStatus;
  TUIStore.update(StoreName.CUSTOM, 'currentContactInfo', {} as IContactInfoType);
  TUIStore.update(StoreName.CUSTOM, 'currentContactListKey', '');
}

function onCurrentContactInfoUpdated(contactInfo: IContactInfoType) {
  currentContactInfo.value = contactInfo;
}

function onCurrentContactListKeyUpdated(contactListKey: string) {
  currentContactListKey.value = contactListKey;
}

provide('userOnlineStatusMap', userOnlineStatusMap);
</script>

<style lang="scss" scoped src="./style/index.scss"></style>
